'use client';

import React from 'react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { zodResolver } from '@hookform/resolvers/zod';
import { useForm } from 'react-hook-form';
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from '@/components/ui/form';
import { Input } from '@/components/ui/input';
import { Textarea } from '@/components/ui/textarea';
import { Switch } from '@/components/ui/switch';
import { Button } from '@/components/ui/button';
import { PermissionTree } from '@/components/system';
import { Badge } from '@/components/ui/badge';
import { Checkbox } from '@/components/ui/checkbox';
import {
  Tabs,
  TabsContent,
  TabsList,
  TabsTrigger,
} from '@/components/ui/tabs';
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogDescription,
  DialogFooter,
} from '@/components/ui/dialog';
import { toast } from 'sonner';
import {
  adminRoleService,
  adminUserService,
} from '@/lib/api/services/admin-management-service.js';
import { Search, UserPlus, Users as UsersIcon } from 'lucide-react';

const STATUS_LABEL = {
  active: '启用',
  inactive: '禁用',
  banned: '封禁',
};

const STATUS_VARIANT = {
  active: 'default',
  inactive: 'secondary',
  banned: 'destructive',
};

const formatDateTime = (value) => {
  if (!value) return '-';
  try {
    return new Date(value).toLocaleString('zh-CN', {
      year: 'numeric',
      month: '2-digit',
      day: '2-digit',
      hour: '2-digit',
      minute: '2-digit',
    });
  } catch (_error) {
    return value;
  }
};
import { getRoleFormSchema } from './role-form-schema.js';

const normalizeDefaultValues = (defaultValues = {}) => ({
  name: defaultValues.name ?? '',
  displayName: defaultValues.displayName ?? '',
  description: defaultValues.description ?? '',
  sortOrder:
    typeof defaultValues.sortOrder === 'number'
      ? defaultValues.sortOrder
      : 0,
  systemRole: Boolean(defaultValues.systemRole),
  permissionIds:
    (defaultValues.permissionIds ??
      defaultValues.permissions?.map((item) => item.id) ??
      []).map(Number),
});

function RoleForm({
  mode = 'create',
  defaultValues,
  permissionTree = [],
  onSubmit,
  onCancel,
  isSubmitting = false,
  disableName = false,
  disableSystemRoleToggle = false,
}) {
  const schema = React.useMemo(() => getRoleFormSchema(mode), [mode]);

  const form = useForm({
    resolver: zodResolver(schema),
    defaultValues: normalizeDefaultValues(defaultValues),
  });

  const [permissionIds, setPermissionIds] = React.useState(
    normalizeDefaultValues(defaultValues).permissionIds,
  );
  const queryClient = useQueryClient();
  const roleId = defaultValues?.id ?? null;
  const canManageMembers = mode === 'edit' && Boolean(roleId);
  const MEMBERS_PAGE_SIZE = 10;
  const [memberPage, setMemberPage] = React.useState(1);
  const [selectedMemberIds, setSelectedMemberIds] = React.useState([]);
  const [isMemberSelectorOpen, setIsMemberSelectorOpen] = React.useState(false);

  React.useEffect(() => {
    const normalized = normalizeDefaultValues(defaultValues);
    form.reset(normalized);
    setPermissionIds(normalized.permissionIds);
    setMemberPage(1);
    setSelectedMemberIds([]);
  }, [defaultValues, form]);

  const roleMembersQueryKey = React.useMemo(
    () => ['role-members', roleId, { page: memberPage, pageSize: MEMBERS_PAGE_SIZE }],
    [roleId, memberPage],
  );

  const {
    data: roleMembersData,
    isLoading: isLoadingMembers,
    isFetching: isFetchingMembers,
  } = useQuery({
    queryKey: roleMembersQueryKey,
    queryFn: () =>
      adminRoleService.listRoleUsers(roleId, {
        page: memberPage,
        pageSize: MEMBERS_PAGE_SIZE,
      }),
    enabled: canManageMembers,
    keepPreviousData: true,
  });

  const roleMembers = React.useMemo(
    () => (roleMembersData?.data ?? []).map((member) => member),
    [roleMembersData],
  );

  const roleMembersMeta = React.useMemo(
    () => ({
      page: roleMembersData?.page ?? memberPage,
      pageSize: roleMembersData?.pageSize ?? MEMBERS_PAGE_SIZE,
      total: roleMembersData?.total ?? 0,
      totalPages: roleMembersData?.totalPages ?? 1,
    }),
    [roleMembersData, memberPage],
  );

  React.useEffect(() => {
    if (!canManageMembers) return;
    if (
      roleMembersMeta.totalPages > 0 &&
      memberPage > roleMembersMeta.totalPages
    ) {
      setMemberPage(roleMembersMeta.totalPages);
    }
  }, [canManageMembers, memberPage, roleMembersMeta.totalPages]);

  React.useEffect(() => {
    if (!canManageMembers) {
      setSelectedMemberIds([]);
      return;
    }
    setSelectedMemberIds((prev) => {
      const currentIds = roleMembers.map((member) => member.id);
      const filtered = prev.filter((id) => currentIds.includes(id));
      const unchanged =
        filtered.length === prev.length &&
        filtered.every((id, index) => id === prev[index]);
      return unchanged ? prev : filtered;
    });
  }, [roleMembers, canManageMembers]);

  const existingMemberIds = React.useMemo(() => {
    if (!canManageMembers) return [];
    const cached = queryClient.getQueriesData({
      queryKey: ['role-members', roleId],
    });
    const set = new Set();
    cached.forEach(([, data]) => {
      const list = data?.data ?? [];
      if (Array.isArray(list)) {
        list.forEach((item) => {
          if (item?.id) {
            set.add(item.id);
          }
        });
      }
    });
    return Array.from(set);
  }, [canManageMembers, queryClient, roleId, roleMembersData]);

  const addMembersMutation = useMutation({
    mutationFn: (userIds) =>
      adminRoleService.addRoleUsers(roleId, {
        userIds,
      }),
    onSuccess: () => {
      toast.success('已成功添加角色成员');
      queryClient.invalidateQueries({ queryKey: ['role-members', roleId] });
      setIsMemberSelectorOpen(false);
    },
    onError: (error) => {
      toast.error(error?.message ?? '添加角色成员失败');
    },
  });

  const removeMembersMutation = useMutation({
    mutationFn: (userIds) =>
      adminRoleService.removeRoleUsers(roleId, {
        userIds,
      }),
    onSuccess: () => {
      toast.success('已移除选中的成员');
      queryClient.invalidateQueries({ queryKey: ['role-members', roleId] });
      setSelectedMemberIds([]);
    },
    onError: (error) => {
      toast.error(error?.message ?? '移除角色成员失败');
    },
  });

  const handleSubmit = form.handleSubmit((values) => {
    const payload = {
      ...values,
      sortOrder:
        typeof values.sortOrder === 'number'
          ? values.sortOrder
          : Number(values.sortOrder || 0),
      permissionIds,
    };

    onSubmit?.(payload);
  });

  const allMemberIds = React.useMemo(
    () => roleMembers.map((member) => member.id),
    [roleMembers],
  );

  const allMembersSelected =
    allMemberIds.length > 0 &&
    allMemberIds.every((id) => selectedMemberIds.includes(id));

  const partiallySelectedMembers =
    selectedMemberIds.length > 0 && !allMembersSelected;

  const handleToggleMember = React.useCallback((id, shouldSelect) => {
    setSelectedMemberIds((prev) => {
      if (shouldSelect) {
        return prev.includes(id) ? prev : [...prev, id];
      }
      return prev.filter((item) => item !== id);
    });
  }, []);

  const handleToggleAllMembers = React.useCallback(
    (checked) => {
      if (checked === true) {
        setSelectedMemberIds(allMemberIds);
      } else {
        setSelectedMemberIds([]);
      }
    },
    [allMemberIds],
  );

  const handleRemoveMembers = React.useCallback(() => {
    if (selectedMemberIds.length === 0 || !roleId) {
      toast.warning('请选择需要移除的成员');
      return;
    }
    removeMembersMutation.mutate(selectedMemberIds);
  }, [removeMembersMutation, roleId, selectedMemberIds]);

  return (
    <Form {...form}>
      <form className="space-y-5" onSubmit={handleSubmit}>
        <Tabs defaultValue="basic" className="space-y-5">
          <TabsList variant="line" size="md">
            <TabsTrigger value="basic">基础信息</TabsTrigger>
            <TabsTrigger value="permissions">权限配置</TabsTrigger>
            {canManageMembers && <TabsTrigger value="members">关联用户</TabsTrigger>}
          </TabsList>

          <TabsContent value="basic" className="space-y-5">
            <div className="grid gap-5 md:grid-cols-2">
              <FormField
                control={form.control}
                name="name"
                render={({ field }) => (
                  <FormItem>
                    <FormLabel>角色标识</FormLabel>
                    <FormControl>
                      <Input
                        placeholder="如 admin、editor"
                        disabled={disableName || mode === 'edit'}
                        {...field}
                      />
                    </FormControl>
                    <FormMessage />
                  </FormItem>
                )}
              />

              <FormField
                control={form.control}
                name="displayName"
                render={({ field }) => (
                  <FormItem>
                    <FormLabel>角色名称</FormLabel>
                    <FormControl>
                      <Input placeholder="如 管理员、编辑" {...field} />
                    </FormControl>
                    <FormMessage />
                  </FormItem>
                )}
              />
            </div>

            <FormField
              control={form.control}
              name="description"
              render={({ field }) => (
                <FormItem>
                  <FormLabel>角色描述</FormLabel>
                  <FormControl>
                    <Textarea
                      placeholder="描述角色职责、适用场景等内容"
                      rows={3}
                      {...field}
                    />
                  </FormControl>
                  <FormMessage />
                </FormItem>
              )}
            />

            <div className="grid gap-5 md:grid-cols-2">
              <FormField
                control={form.control}
                name="sortOrder"
                render={({ field }) => (
                  <FormItem>
                    <FormLabel>排序值</FormLabel>
                    <FormControl>
                      <Input
                        type="number"
                        placeholder="默认 0"
                        {...field}
                        value={field.value ?? 0}
                        onChange={(event) =>
                          field.onChange(Number(event.target.value))
                        }
                      />
                    </FormControl>
                    <FormMessage />
                  </FormItem>
                )}
              />

              <FormField
                control={form.control}
                name="systemRole"
                render={({ field }) => (
                  <FormItem className="flex flex-col gap-2.5">
                    <FormLabel>系统内置角色</FormLabel>
                    <div className="flex items-center gap-3 rounded-md border border-dashed border-muted px-4 py-3">
                      <Switch
                        checked={field.value}
                        onCheckedChange={field.onChange}
                        disabled={disableSystemRoleToggle}
                      />
                      <div className="flex flex-col text-sm">
                        <span className="font-medium">
                          {field.value ? '系统角色' : '自定义角色'}
                        </span>
                        <span className="text-xs text-muted-foreground">
                          系统角色通常不可删除，可限制在关键模块的权限调整
                        </span>
                      </div>
                    </div>
                    <FormMessage />
                  </FormItem>
                )}
              />
            </div>
          </TabsContent>

          <TabsContent value="permissions">
            <div className="space-y-3">
              <div className="flex items-center justify-between">
                <FormLabel className="mb-0">权限配置</FormLabel>
                <span className="text-xs text-muted-foreground">
                  已选择 {permissionIds.length} 项
                </span>
              </div>
              <div className="max-h-[480px] overflow-y-auto rounded-lg border border-border/60 bg-muted/20 px-3 py-3">
                <PermissionTree
                  data={permissionTree}
                  value={permissionIds}
                  onChange={setPermissionIds}
                  defaultExpandAll={false}
                  className="space-y-3"
                />
              </div>
            </div>
          </TabsContent>

          {canManageMembers && (
            <TabsContent value="members" className="space-y-4">
              <div className="flex flex-wrap items-center justify-between gap-3">
                <div className="flex items-center gap-2">
                  <Button
                    size="sm"
                    type="button"
                    onClick={() => setIsMemberSelectorOpen(true)}
                    disabled={addMembersMutation.isPending}
                  >
                    <UserPlus className="size-4 mr-1.5" />
                    添加成员
                  </Button>
                  <Button
                    size="sm"
                    variant="destructive"
                    disabled={
                      selectedMemberIds.length === 0 || removeMembersMutation.isPending
                    }
                    onClick={handleRemoveMembers}
                  >
                    批量移除
                  </Button>
                </div>
                <div className="flex items-center gap-2 text-sm text-muted-foreground">
                  <UsersIcon className="size-4" />
                  共 {roleMembersMeta.total} 人
                </div>
              </div>

              <div className="border border-border/70 rounded-lg divide-y">
                {isLoadingMembers ? (
                  <div className="py-10 text-center text-sm text-muted-foreground">
                    正在加载角色成员…
                  </div>
                ) : roleMembers.length === 0 ? (
                  <div className="py-10 text-center text-sm text-muted-foreground">
                    该角色暂未关联任何用户。
                  </div>
                ) : (
                  <>
                    <div className="flex items-center gap-3 px-4 py-3 bg-muted/40">
                      <Checkbox
                        checked={
                          allMembersSelected
                            ? true
                            : partiallySelectedMembers
                              ? 'indeterminate'
                              : false
                        }
                        onCheckedChange={handleToggleAllMembers}
                        aria-label="选择全部成员"
                      />
                      <span className="text-xs text-muted-foreground">
                        已选 {selectedMemberIds.length} / {roleMembersMeta.pageSize}
                      </span>
                    </div>
                    {roleMembers.map((member) => (
                      <div
                        key={member.id}
                        className="flex items-start gap-3 px-4 py-3"
                      >
                        <Checkbox
                          checked={selectedMemberIds.includes(member.id)}
                          onCheckedChange={(checked) =>
                            handleToggleMember(member.id, checked === true)
                          }
                          aria-label={`选择用户 ${member.email}`}
                        />
                        <div className="flex-1 min-w-0 space-y-1">
                          <div className="flex flex-wrap items-center gap-2">
                            <span className="font-medium truncate">
                              {member.fullName || '未填写姓名'}
                            </span>
                            <Badge variant="outline" className="font-normal">
                              {member.email}
                            </Badge>
                            <Badge variant={STATUS_VARIANT[member.status] || 'secondary'}>
                              {STATUS_LABEL[member.status] ?? member.status ?? '未知状态'}
                            </Badge>
                          </div>
                          <div className="text-xs text-muted-foreground">
                            用户名：{member.username}
                          </div>
                          <div className="text-xs text-muted-foreground">
                            最近登录：{formatDateTime(member.lastSignInAt)}
                          </div>
                        </div>
                      </div>
                    ))}
                  </>
                )}
              </div>

              {roleMembersMeta.totalPages > 1 && (
                <div className="flex flex-wrap items-center justify-between gap-3 text-sm text-muted-foreground">
                  <div>
                    第 {(roleMembersMeta.page - 1) * roleMembersMeta.pageSize + 1} -
                    {' '}
                    {Math.min(roleMembersMeta.page * roleMembersMeta.pageSize, roleMembersMeta.total)} 条
                  </div>
                  <div className="flex items-center gap-2">
                    <Button
                      variant="outline"
                      size="sm"
                      disabled={roleMembersMeta.page <= 1 || isFetchingMembers}
                      onClick={() => setMemberPage((prev) => Math.max(prev - 1, 1))}
                    >
                      上一页
                    </Button>
                    <span>
                      {roleMembersMeta.page} / {roleMembersMeta.totalPages}
                    </span>
                    <Button
                      variant="outline"
                      size="sm"
                      disabled={
                        roleMembersMeta.page >= roleMembersMeta.totalPages || isFetchingMembers
                      }
                      onClick={() =>
                        setMemberPage((prev) =>
                          Math.min(prev + 1, roleMembersMeta.totalPages),
                        )
                      }
                    >
                      下一页
                    </Button>
                  </div>
                </div>
              )}
            </TabsContent>
          )}
        </Tabs>

        {canManageMembers && (
          <RoleMemberSelectorDialog
            open={isMemberSelectorOpen}
            onOpenChange={(open) => {
              if (addMembersMutation.isPending) return;
              setIsMemberSelectorOpen(open);
            }}
            existingMemberIds={existingMemberIds}
            isSubmitting={addMembersMutation.isPending}
            onConfirm={(userIds) => {
              if (!userIds || userIds.length === 0) {
                toast.warning('请至少选择一位用户');
                return;
              }
              addMembersMutation.mutate(userIds);
            }}
          />
        )}

        <div className="flex flex-col-reverse gap-2 pt-2 sm:flex-row sm:justify-end">
          <Button
            type="button"
            variant="outline"
            disabled={isSubmitting || addMembersMutation.isPending}
            onClick={onCancel}
          >
            取消
          </Button>
          <Button type="submit" disabled={isSubmitting}>
            {isSubmitting
              ? '提交中…'
              : mode === 'create'
              ? '创建角色'
              : '保存变更'}
          </Button>
        </div>
      </form>
    </Form>
  );
}

function RoleMemberSelectorDialog({
  open,
  onOpenChange,
  onConfirm,
  existingMemberIds = [],
  isSubmitting = false,
}) {
  const PAGE_SIZE = 10;
  const [keyword, setKeyword] = React.useState('');
  const [page, setPage] = React.useState(1);
  const [selectedIds, setSelectedIds] = React.useState([]);

  React.useEffect(() => {
    if (open) {
      setKeyword('');
      setPage(1);
      setSelectedIds([]);
    }
  }, [open]);

  const queryKey = React.useMemo(
    () => ['role-member-selector', { open, keyword, page }],
    [open, keyword, page],
  );

  const { data, isLoading, isFetching } = useQuery({
    queryKey,
    queryFn: () =>
      adminUserService.getList({
        page,
        pageSize: PAGE_SIZE,
        keyword: keyword.trim() || undefined,
      }),
    enabled: open,
    keepPreviousData: true,
  });

  const existingSet = React.useMemo(
    () => new Set(existingMemberIds),
    [existingMemberIds],
  );

  const users = React.useMemo(() => {
    const list = data?.data ?? [];
    return list.filter((user) => !existingSet.has(user.id));
  }, [data, existingSet]);

  const meta = React.useMemo(
    () => ({
      page: data?.page ?? page,
      pageSize: data?.pageSize ?? PAGE_SIZE,
      total: data?.total ?? 0,
      totalPages: data?.totalPages ?? 1,
    }),
    [data, page],
  );

  const allUserIds = users.map((user) => user.id);
  const allSelected =
    allUserIds.length > 0 && allUserIds.every((id) => selectedIds.includes(id));
  const partiallySelected =
    selectedIds.length > 0 && !allSelected;

  const handleToggle = React.useCallback((id, checked) => {
    setSelectedIds((prev) => {
      if (checked === true) {
        return prev.includes(id) ? prev : [...prev, id];
      }
      return prev.filter((item) => item !== id);
    });
  }, []);

  const handleToggleAll = React.useCallback(
    (checked) => {
      if (checked === true) {
        setSelectedIds(allUserIds);
      } else {
        setSelectedIds([]);
      }
    },
    [allUserIds],
  );

  return (
    <Dialog open={open} onOpenChange={(next) => !isSubmitting && onOpenChange(next)}>
      <DialogContent className="sm:max-w-3xl">
        <DialogHeader>
          <DialogTitle>添加角色成员</DialogTitle>
          <DialogDescription>
            勾选需要加入该角色的用户，可通过关键词快速筛选。
          </DialogDescription>
        </DialogHeader>

        <div className="space-y-4">
          <div className="relative">
            <Search className="absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" />
            <Input
              value={keyword}
              placeholder="搜索邮箱 / 用户名 / 姓名"
              onChange={(event) => {
                setKeyword(event.target.value);
                setPage(1);
              }}
              className="pl-10"
            />
          </div>

          <div className="border border-border/70 rounded-lg divide-y max-h-[360px] overflow-y-auto">
            {isLoading ? (
              <div className="py-12 text-center text-sm text-muted-foreground">
                正在加载可选用户…
              </div>
            ) : users.length === 0 ? (
              <div className="py-12 text-center text-sm text-muted-foreground">
                暂无可添加的用户，可尝试修改搜索条件。
              </div>
            ) : (
              <>
                <div className="flex items-center gap-3 px-4 py-3 bg-muted/40">
                  <Checkbox
                    checked={
                      allSelected ? true : partiallySelected ? 'indeterminate' : false
                    }
                    onCheckedChange={handleToggleAll}
                    aria-label="选择全部待添加用户"
                  />
                  <span className="text-xs text-muted-foreground">
                    已选 {selectedIds.length} / {users.length}
                  </span>
                </div>
                {users.map((user) => (
                  <div key={user.id} className="flex items-start gap-3 px-4 py-3">
                    <Checkbox
                      checked={selectedIds.includes(user.id)}
                      onCheckedChange={(checked) => handleToggle(user.id, checked === true)}
                      aria-label={`选择用户 ${user.email}`}
                    />
                    <div className="flex-1 min-w-0 space-y-1">
                      <div className="flex flex-wrap items-center gap-2">
                        <span className="font-medium truncate">
                          {user.fullName || '未填写姓名'}
                        </span>
                        <Badge variant="outline" className="font-normal">
                          {user.email}
                        </Badge>
                        {user.role?.displayName && (
                          <Badge variant="secondary">
                            当前角色：{user.role.displayName}
                          </Badge>
                        )}
                      </div>
                      <div className="text-xs text-muted-foreground">
                        用户名：{user.username}
                      </div>
                    </div>
                  </div>
                ))}
              </>
            )}
          </div>

          {meta.totalPages > 1 && (
            <div className="flex items-center justify-between text-xs text-muted-foreground">
              <div>
                第 {(meta.page - 1) * meta.pageSize + 1} -
                {' '}
                {Math.min(meta.page * meta.pageSize, meta.total)} 条 / 共 {meta.total} 条
              </div>
              <div className="flex items-center gap-2">
                <Button
                  variant="outline"
                  size="sm"
                  disabled={meta.page <= 1 || isFetching}
                  onClick={() => setPage((prev) => Math.max(prev - 1, 1))}
                >
                  上一页
                </Button>
                <span>
                  {meta.page} / {meta.totalPages}
                </span>
                <Button
                  variant="outline"
                  size="sm"
                  disabled={meta.page >= meta.totalPages || isFetching}
                  onClick={() => setPage((prev) => Math.min(prev + 1, meta.totalPages))}
                >
                  下一页
                </Button>
              </div>
            </div>
          )}
        </div>

        <DialogFooter>
          <Button
            type="button"
            variant="outline"
            disabled={isSubmitting}
            onClick={() => onOpenChange(false)}
          >
            取消
          </Button>
          <Button
            type="button"
            disabled={selectedIds.length === 0 || isSubmitting}
            onClick={() => onConfirm(selectedIds)}
          >
            {isSubmitting ? '提交中…' : '批量添加'}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

export { RoleForm };


